using System;
using Microsoft.SPOT;
using System.Text;

namespace Gadgeteer.Modules.Community.XBee
{
    /// <summary>
    /// Parses TransmitReceive messages
    /// </summary>
    public class TransmitReceive : BaseAPIMessage
    {
        /// <summary>
        /// body of message
        /// </summary>
        public string MessageBody { get; private set; }
        /// <summary>
        /// Source of the message (TODO: this is broken, use uint Hi and Low instead
        /// </summary>
        public ulong SourceAddress64Bit { get; private set; }
        /// <summary>
        /// 16 bit address of the source
        /// </summary>
        public ushort SourceNetworkAddress16Bit { get; private set; }
        /// <summary>
        /// Receive Options
        /// </summary>
        public ushort ReceiveOptions { get; private set; }
        /// <summary>
        /// byte array of received message
        /// </summary>
        public byte[] ReceivedData { get; private set; }


        /// <summary>
        /// Properties for multipart messages, not a XBee construct, this is something I came up with
        /// to handle large messages
        /// </summary>
        public bool MultipartMessage { get; set; }
        /// <summary>
        /// The index of the message
        /// </summary>
        public int MessageOrdinal { get; set; }
        /// <summary>
        /// Total number of messages
        /// </summary>
        public int TotalPacketCount { get; set; }
        /// <summary>
        /// Data type of message
        /// </summary>
        public MessageDataTypeEnum MessageDataType { get; set; }

        /// <summary>
        /// returns APIMessageEnum.TransmitReceive
        /// </summary>
        protected override ushort MessageType
        {
            get { return (ushort)APIMessageEnum.TransmitReceive; }
        }

        /// <summary>
        /// returns APIMessageEnum.TransmitReceive.ToString()
        /// </summary>
        /// <returns>APIMessageEnum.TransmitReceive.ToString()</returns>
        protected override string MessageTypeToString()
        {
            return APIMessageEnum.TransmitReceive.ToString();
        }

        /// <summary>
        /// parses the API message
        /// </summary>
        /// <param name="message">API message</param>
        public override void ParseMessageBody(byte[] message)
        {
            int numEscaped = 0;
            int startOfReceivedDataWhenNoEscaped = 15;
            for (int i = 1; i <startOfReceivedDataWhenNoEscaped; i++)
            {
                if ((ushort)message[i] == (ushort)APIMessageEnum.EscapedByte)
                {
                    numEscaped++;
                    startOfReceivedDataWhenNoEscaped++;
                }
            }

            int startOfReceivedData = startOfReceivedDataWhenNoEscaped;

            if (message[startOfReceivedDataWhenNoEscaped] == (byte)APIMessageEnum.MultiPartMessage)
            {
                MultipartMessage = true;
                // First byte signals that this is a multi part message, 
                // next byte is MSB, then LSB, then the message type and message ordinal
                TotalPacketCount = (int)message[startOfReceivedDataWhenNoEscaped + 1];
                MessageOrdinal = message[startOfReceivedDataWhenNoEscaped + 2];
                MessageDataType = (MessageDataTypeEnum)message[startOfReceivedDataWhenNoEscaped + 3];
                startOfReceivedData += 4;
            }

            ReceivedData = new byte[message.Length - startOfReceivedData - 1];
            Array.Copy(message, startOfReceivedData, ReceivedData, 0, ReceivedData.Length);

            // Todo: the message doesn't have to be a string
            char[] chars =  UTF8Encoding.UTF8.GetChars(ReceivedData);
            MessageBody = new string(chars);
        }

        /// <summary>
        /// override of MessageBodyToString
        /// </summary>
        /// <returns>MessageBody</returns>
        public override string MessageBodyToString()
        {
            return MessageBody;
        }
    }
}
